package cn.iocoder.yudao.module.home.service;

import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.home.controller.admin.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class HomeServiceImpl implements HomeService {

    // 从配置文件注入IP和端口
    @Value("${module.home.api.ip}")
    private String apiIp;

    @Value("${module.home.api.port}")
    private String apiPort;

    // 基础路径（动态拼接IP和端口）
    private String BASE_PATH;
    // 7天数据量统计接口单独基础路径（路径前缀与其他接口不同）
    private String DATA_NUM_7DAY_BASE_PATH;

    // 各接口路径后缀（固定不变部分）
    private static final String TOP_INDEX_SUFFIX = "topIndex";
    private static final String SECTION_OPTIONS_SUFFIX = "getSectionOptions";
    private static final String ACCESS_STATISTICS_SUFFIX = "accessStatistics";
    private static final String CATALOG_INDEX_SUFFIX = "catalogIndex";
    private static final String CATALOG_INDEX_DETAILS_SUFFIX = "catalogIndexDetails";
    private static final String TABLE_RANKING_SUFFIX = "tableRanking";
    private static final String TASK_DISTRIBUTION_SUFFIX = "getTaskDistribution";
    private static final String DATA_NUM_7DAY_SUFFIX = "getDataNumBy7Day";
    private static final String DATA_SOURCES_SUFFIX = "dataSources";
    private static final String DATA_STD_STATISTICS_SUFFIX = "dataStdStatistics";

    // 公共认证Token
    private static final String AUTH_TOKEN = "Bearer 1q2w3e4r5t6y7u8i9o0p";

    // 初始化基础路径（Bean创建时执行，确保IP/端口注入后再拼接）
    @PostConstruct
    public void initBasePath() {
        this.BASE_PATH = String.format("https://%s:%s/app/cmcc/data/dataasset/screen/", apiIp, apiPort);
        this.DATA_NUM_7DAY_BASE_PATH = String.format("https://%s:%s/app/cmcc/data/datacollect/overview/", apiIp, apiPort);
    }

    @Override
    public HomeTopIndexRespVO getTopIndex() {
        log.info("[getTopIndex][开始调用首页TOP指标接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL，发起GET请求（接口无参数）
            String requestUrl = BASE_PATH + TOP_INDEX_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getTopIndex][接口返回空响应]");
                throw new ServiceException("首页TOP指标接口返回空响应");
            }
            log.info("[getTopIndex][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("首页TOP指标响应解析失败，格式非法");
            }

            // 4. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("首页TOP指标查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getTopIndex][{}]", errorMsg);
                throw new ServiceException(errorMsg);
            }

            // 5. 提取核心data字段
            Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
            if (dataMap == null) {
                log.warn("[getTopIndex][接口返回data字段为空]");
                throw new ServiceException("首页TOP指标查询无有效数据");
            }

            // 6. 转换为VO对象
            HomeTopIndexRespVO resultVO = convertToHomeTopIndexRespVO(dataMap);

            log.info("[getTopIndex][接口调用成功]");
            return resultVO;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getTopIndex][接口调用异常]", e);
            throw new ServiceException("首页TOP指标查询异常：" + e.getMessage());
        }
    }

    @Override
    public List<SectionOptionVO> getSectionOptions(String hierarchy) {
        log.info("[getSectionOptions][开始获取图表配置选项](hierarchy: {})", hierarchy);

        try {
            // 1. 参数校验
            if (hierarchy == null || hierarchy.trim().isEmpty()) {
                throw new ServiceException("层级参数不能为空");
            }

            // 2. 动态拼接请求URL，URL编码参数
            String encodedHierarchy = URLEncoder.encode(hierarchy, StandardCharsets.UTF_8.name());
            String requestUrl = String.format("%s%s?hierarchy=%s", BASE_PATH, SECTION_OPTIONS_SUFFIX, encodedHierarchy);
            log.info("[getSectionOptions][请求URL](url: {})", requestUrl);

            // 3. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 4. 发起GET请求
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getSectionOptions][接口返回空响应](hierarchy: {})", hierarchy);
                throw new ServiceException("图表配置选项接口返回空响应");
            }
            log.info("[getSectionOptions][接口响应内容](hierarchy: {}): {}", hierarchy, response);

            // 5. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("图表配置选项响应解析失败，格式非法");
            }

            // 6. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("图表配置选项查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getSectionOptions][{}](hierarchy: {})", errorMsg, hierarchy);
                throw new ServiceException(errorMsg);
            }

            // 7. 提取核心data字段
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) responseMap.get("data");
            if (dataList == null) {
                log.warn("[getSectionOptions][接口返回data列表为空](hierarchy: {})", hierarchy);
                return new ArrayList<>();
            }

            // 8. 转换为VO列表
            List<SectionOptionVO> resultList = convertToSectionOptionVOList(dataList);

            log.info("[getSectionOptions][接口调用成功](hierarchy: {}, 数据条数: {})",
                    hierarchy, resultList.size());
            return resultList;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getSectionOptions][接口调用异常](hierarchy: {})", hierarchy, e);
            throw new ServiceException("图表配置选项查询异常：" + e.getMessage());
        }
    }

    @Override
    public AccessStatisticsRespVO getAccessStatistics() {
        log.info("[getAccessStatistics][开始调用系统接入统计接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL，发起GET请求（接口无参数）
            String requestUrl = BASE_PATH + ACCESS_STATISTICS_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getAccessStatistics][接口返回空响应]");
                throw new ServiceException("系统接入统计接口返回空响应");
            }
            log.info("[getAccessStatistics][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("系统接入统计响应解析失败，格式非法");
            }

            // 4. 转换为VO对象（无论成功失败都返回原始数据）
            AccessStatisticsRespVO resultVO = convertToAccessStatisticsRespVO(responseMap);

            // 5. 如果接口返回失败状态，记录警告日志但不抛出异常，让前端处理
            Boolean success = (Boolean) responseMap.get("success");
            Integer code = (Integer) responseMap.get("code");
            if (Boolean.FALSE.equals(success) || (code != null && code != 200)) {
                String errorMsg = String.format("系统接入统计接口返回失败状态：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.warn("[getAccessStatistics][{}]", errorMsg);
                // 不抛出异常，返回原始错误信息给前端
            } else {
                log.info("[getAccessStatistics][接口调用成功]");
            }

            return resultVO;

        } catch (Exception e) {
            log.error("[getAccessStatistics][接口调用异常]", e);

            // 返回一个包含错误信息的响应对象，而不是抛出异常
            AccessStatisticsRespVO errorVO = new AccessStatisticsRespVO();
            errorVO.setSuccess(false);
            errorVO.setCode(500);
            errorVO.setMessage("系统接入统计接口调用异常：" + e.getMessage());
            errorVO.setData(null);
            errorVO.setPageInfo(null);
            errorVO.setExt(null);

            return errorVO;
        }
    }

    @Override
    public List<CatalogIndexItemVO> getCatalogIndex(CatalogIndexReqVO reqVO) {
        log.info("[getCatalogIndex][开始调用目录指标接口](reqVO: {})", JsonUtils.toJsonString(reqVO));

        try {
            // 1. 参数校验
            if (reqVO == null || reqVO.getParentId() == null || reqVO.getParentId().trim().isEmpty()) {
                throw new ServiceException("父级目录ID不能为空");
            }

            // 2. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 3. 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("parentId", reqVO.getParentId());
            requestBody.put("sortName", reqVO.getSortName());
            requestBody.put("sortOrder", reqVO.getSortOrder());

            String requestJson = JsonUtils.toJsonString(requestBody);
            String requestUrl = BASE_PATH + CATALOG_INDEX_SUFFIX;
            log.info("[getCatalogIndex][请求参数](url: {}, body: {})", requestUrl, requestJson);

            // 4. 发起POST请求
            String response = HttpUtils.post(requestUrl, headers, requestJson);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getCatalogIndex][接口返回空响应](parentId: {})", reqVO.getParentId());
                throw new ServiceException("目录指标接口返回空响应");
            }
            log.info("[getCatalogIndex][接口响应内容](parentId: {}): {}", reqVO.getParentId(), response);

            // 5. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("目录指标响应解析失败，格式非法");
            }

            // 6. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("目录指标查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getCatalogIndex][{}](parentId: {})", errorMsg, reqVO.getParentId());
                throw new ServiceException(errorMsg);
            }

            // 7. 提取核心data字段
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) responseMap.get("data");
            if (dataList == null) {
                log.warn("[getCatalogIndex][接口返回data列表为空](parentId: {})", reqVO.getParentId());
                return new ArrayList<>();
            }

            // 8. 转换为VO列表
            List<CatalogIndexItemVO> resultList = convertToCatalogIndexItemVOList(dataList);

            log.info("[getCatalogIndex][接口调用成功](parentId: {}, 数据条数: {})",
                    reqVO.getParentId(), resultList.size());
            return resultList;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getCatalogIndex][接口调用异常](parentId: {})",
                    reqVO != null ? reqVO.getParentId() : "null", e);
            throw new ServiceException("目录指标查询异常：" + e.getMessage());
        }
    }

    @Override
    public CatalogIndexDetailsRespVO getCatalogIndexDetails(CatalogIndexDetailsReqVO reqVO) {
        log.info("[getCatalogIndexDetails][开始调用目录指标详情接口](reqVO: {})", JsonUtils.toJsonString(reqVO));

        try {
            // 1. 参数校验
            if (reqVO == null) {
                throw new ServiceException("请求参数不能为空");
            }
            if (reqVO.getLevel() == null) {
                throw new ServiceException("层级不能为空");
            }
            if (reqVO.getHierarchyId() == null || reqVO.getHierarchyId().trim().isEmpty()) {
                throw new ServiceException("层级ID不能为空");
            }

            // 2. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 3. 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("level", reqVO.getLevel());
            requestBody.put("hierarchyId", reqVO.getHierarchyId());
            requestBody.put("sortName", reqVO.getSortName());
            requestBody.put("sortOrder", reqVO.getSortOrder());
            requestBody.put("pageNo", reqVO.getPageNo());
            requestBody.put("pageSize", reqVO.getPageSize());

            String requestJson = JsonUtils.toJsonString(requestBody);
            String requestUrl = BASE_PATH + CATALOG_INDEX_DETAILS_SUFFIX;
            log.info("[getCatalogIndexDetails][请求参数](url: {}, body: {})", requestUrl, requestJson);

            // 4. 发起POST请求
            String response = HttpUtils.post(requestUrl, headers, requestJson);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getCatalogIndexDetails][接口返回空响应](level: {}, hierarchyId: {})",
                        reqVO.getLevel(), reqVO.getHierarchyId());
                throw new ServiceException("目录指标详情接口返回空响应");
            }
            log.info("[getCatalogIndexDetails][接口响应内容](level: {}, hierarchyId: {}): {}",
                    reqVO.getLevel(), reqVO.getHierarchyId(), response);

            // 5. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("目录指标详情响应解析失败，格式非法");
            }

            // 6. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("目录指标详情查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getCatalogIndexDetails][{}](level: {}, hierarchyId: {})",
                        errorMsg, reqVO.getLevel(), reqVO.getHierarchyId());
                throw new ServiceException(errorMsg);
            }

            // 7. 转换为响应VO
            CatalogIndexDetailsRespVO resultVO = convertToCatalogIndexDetailsRespVO(responseMap);

            log.info("[getCatalogIndexDetails][接口调用成功](level: {}, hierarchyId: {}, 数据条数: {})",
                    reqVO.getLevel(), reqVO.getHierarchyId(),
                    resultVO.getData() != null ? resultVO.getData().size() : 0);
            return resultVO;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getCatalogIndexDetails][接口调用异常](level: {}, hierarchyId: {})",
                    reqVO != null ? reqVO.getLevel() : "null",
                    reqVO != null ? reqVO.getHierarchyId() : "null", e);
            throw new ServiceException("目录指标详情查询异常：" + e.getMessage());
        }
    }

    @Override
    public TableRankingRespVO getTableRanking(TableRankingReqVO reqVO) {
        log.info("[getTableRanking][开始调用表数据排名接口](reqVO: {})", JsonUtils.toJsonString(reqVO));

        try {
            // 1. 参数校验
            if (reqVO == null || reqVO.getHierarchyId() == null || reqVO.getHierarchyId().trim().isEmpty()) {
                throw new ServiceException("层级ID不能为空");
            }

            // 2. 动态拼接请求URL，URL编码参数
            String encodedHierarchyId = URLEncoder.encode(reqVO.getHierarchyId(), StandardCharsets.UTF_8.name());
            String requestUrl = String.format("%s%s?hierarchyId=%s", BASE_PATH, TABLE_RANKING_SUFFIX, encodedHierarchyId);
            log.info("[getTableRanking][请求URL](url: {})", requestUrl);

            // 3. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 4. 发起GET请求
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getTableRanking][接口返回空响应](hierarchyId: {})", reqVO.getHierarchyId());
                throw new ServiceException("表数据排名接口返回空响应");
            }
            log.info("[getTableRanking][接口响应内容](hierarchyId: {}): {}", reqVO.getHierarchyId(), response);

            // 5. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("表数据排名响应解析失败，格式非法");
            }

            // 6. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("表数据排名查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getTableRanking][{}](hierarchyId: {})", errorMsg, reqVO.getHierarchyId());
                throw new ServiceException(errorMsg);
            }

            // 7. 提取核心data字段
            Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
            if (dataMap == null) {
                log.warn("[getTableRanking][接口返回data字段为空](hierarchyId: {})", reqVO.getHierarchyId());
                throw new ServiceException("表数据排名查询无有效数据");
            }

            // 8. 转换为VO对象
            TableRankingRespVO resultVO = convertToTableRankingRespVO(dataMap);

            log.info("[getTableRanking][接口调用成功](hierarchyId: {}, 数据空间排名条数: {}, 数据数量排名条数: {})",
                    reqVO.getHierarchyId(),
                    resultVO.getDataSpace() != null ? resultVO.getDataSpace().size() : 0,
                    resultVO.getDataNum() != null ? resultVO.getDataNum().size() : 0);
            return resultVO;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getTableRanking][接口调用异常](hierarchyId: {})",
                    reqVO != null ? reqVO.getHierarchyId() : "null", e);
            throw new ServiceException("表数据排名查询异常：" + e.getMessage());
        }
    }

    @Override
    public TaskDistributionRespVO getTaskDistribution() {
        log.info("[getTaskDistribution][开始调用汇聚任务分布统计接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL，发起GET请求（接口无参数）
            String requestUrl = BASE_PATH + TASK_DISTRIBUTION_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getTaskDistribution][接口返回空响应]");
                throw new ServiceException("汇聚任务分布统计接口返回空响应");
            }
            log.info("[getTaskDistribution][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("汇聚任务分布统计响应解析失败，格式非法");
            }

            // 4. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("汇聚任务分布统计查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getTaskDistribution][{}]", errorMsg);
                throw new ServiceException(errorMsg);
            }

            // 5. 提取核心data字段
            Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
            if (dataMap == null) {
                log.warn("[getTaskDistribution][接口返回data字段为空]");
                throw new ServiceException("汇聚任务分布统计查询无有效数据");
            }

            // 6. 转换为VO对象
            TaskDistributionRespVO resultVO = convertToTaskDistributionRespVO(dataMap);

            log.info("[getTaskDistribution][接口调用成功](任务总数: {}, DAG任务数: {}, CDC任务数: {})",
                    resultVO.getTaskNum(), resultVO.getDagNum(), resultVO.getCdcNum());
            return resultVO;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getTaskDistribution][接口调用异常]", e);
            throw new ServiceException("汇聚任务分布统计查询异常：" + e.getMessage());
        }
    }

    @Override
    public List<DataNum7DayItemVO> getDataNumBy7Day() {
        log.info("[getDataNumBy7Day][开始调用7天数据量统计接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL（使用单独的基础路径），发起GET请求
            String requestUrl = DATA_NUM_7DAY_BASE_PATH + DATA_NUM_7DAY_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getDataNumBy7Day][接口返回空响应]");
                throw new ServiceException("7天数据量统计接口返回空响应");
            }
            log.info("[getDataNumBy7Day][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("7天数据量统计响应解析失败，格式非法");
            }

            // 4. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("7天数据量统计查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getDataNumBy7Day][{}]", errorMsg);
                throw new ServiceException(errorMsg);
            }

            // 5. 提取核心data字段
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) responseMap.get("data");
            if (dataList == null || dataList.isEmpty()) {
                log.warn("[getDataNumBy7Day][接口返回data列表为空]");
                return new ArrayList<>();
            }

            // 6. 转换为VO列表
            List<DataNum7DayItemVO> resultList = convertToDataNum7DayItemVOList(dataList);

            log.info("[getDataNumBy7Day][接口调用成功]，共获取{}天数据", resultList.size());
            return resultList;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getDataNumBy7Day][接口调用异常]", e);
            throw new ServiceException("7天数据量统计查询异常：" + e.getMessage());
        }
    }

    @Override
    public List<DataSourceVO> getDataSources() {
        log.info("[getDataSources][开始调用数据源列表接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL，发起GET请求（接口无参数）
            String requestUrl = BASE_PATH + DATA_SOURCES_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getDataSources][接口返回空响应]");
                throw new ServiceException("数据源列表接口返回空响应");
            }
            log.info("[getDataSources][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("数据源列表响应解析失败，格式非法");
            }

            // 4. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("数据源列表查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getDataSources][{}]", errorMsg);
                throw new ServiceException(errorMsg);
            }

            // 5. 提取核心data字段
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) responseMap.get("data");
            if (dataList == null || dataList.isEmpty()) {
                log.warn("[getDataSources][接口返回data列表为空]");
                return new ArrayList<>();
            }

            // 6. 转换为VO列表
            List<DataSourceVO> resultList = convertToDataSourceVOList(dataList);

            log.info("[getDataSources][接口调用成功]，共获取{}个数据源", resultList.size());
            return resultList;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getDataSources][接口调用异常]", e);
            throw new ServiceException("数据源列表查询异常：" + e.getMessage());
        }
    }

    @Override
    public DataStdStatisticsRespVO getDataStdStatistics() {
        log.info("[getDataStdStatistics][开始调用数据标准统计接口]");

        try {
            // 1. 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", AUTH_TOKEN);
            headers.put("Content-Type", "application/json;charset=UTF-8");
            headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 2. 动态拼接请求URL，发起GET请求（接口无参数）
            String requestUrl = BASE_PATH + DATA_STD_STATISTICS_SUFFIX;
            String response = HttpUtils.get(requestUrl, headers);
            if (response == null || response.trim().isEmpty()) {
                log.error("[getDataStdStatistics][接口返回空响应]");
                throw new ServiceException("数据标准统计接口返回空响应");
            }
            log.info("[getDataStdStatistics][接口响应内容]：{}", response);

            // 3. 解析响应
            Map<String, Object> responseMap = JsonUtils.parseObject(response, Map.class);
            if (responseMap == null) {
                throw new ServiceException("数据标准统计响应解析失败，格式非法");
            }

            // 4. 校验响应状态
            Integer code = (Integer) responseMap.get("code");
            Boolean success = (Boolean) responseMap.get("success");
            if (code == null || code != 200 || Boolean.FALSE.equals(success)) {
                String errorMsg = String.format("数据标准统计查询失败：code=%s，message=%s，success=%s",
                        code, responseMap.get("message"), success);
                log.error("[getDataStdStatistics][{}]", errorMsg);
                throw new ServiceException(errorMsg);
            }

            // 5. 提取核心data字段
            Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
            if (dataMap == null) {
                log.warn("[getDataStdStatistics][接口返回data字段为空]");
                throw new ServiceException("数据标准统计查询无有效数据");
            }

            // 6. 转换为VO对象
            DataStdStatisticsRespVO resultVO = convertToDataStdStatisticsRespVO(dataMap);

            log.info("[getDataStdStatistics][接口调用成功](词条: {}, 数据元: {}, 代码集: {}, 计量单位: {})",
                    resultVO.getWord(), resultVO.getElement(),
                    resultVO.getCodeset(), resultVO.getUnit());
            return resultVO;

        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("[getDataStdStatistics][接口调用异常]", e);
            throw new ServiceException("数据标准统计查询异常：" + e.getMessage());
        }
    }

    /**
     * 将数据Map转换为DataStdStatisticsRespVO
     */
    private DataStdStatisticsRespVO convertToDataStdStatisticsRespVO(Map<String, Object> dataMap) {
        DataStdStatisticsRespVO vo = new DataStdStatisticsRespVO();

        vo.setWord(getStringSafely(dataMap, "WORD"));
        vo.setElement(getStringSafely(dataMap, "ELEMENT"));
        vo.setUnit(getStringSafely(dataMap, "UNIT"));
        vo.setColumnNum(getStringSafely(dataMap, "columnNum"));
        vo.setTableNum(getStringSafely(dataMap, "tableNum"));
        vo.setCodeset(getStringSafely(dataMap, "CODESET"));
        vo.setFile(getStringSafely(dataMap, "FILE"));
        vo.setName(getStringSafely(dataMap, "NAME"));

        return vo;
    }

    /**
     * 将数据列表转换为DataSourceVO列表
     */
    private List<DataSourceVO> convertToDataSourceVOList(List<Map<String, Object>> dataList) {
        List<DataSourceVO> resultList = new ArrayList<>();

        for (Map<String, Object> itemMap : dataList) {
            DataSourceVO vo = new DataSourceVO();

            vo.setOffset(getIntegerSafely(itemMap, "offset"));
            vo.setSize(getIntegerSafely(itemMap, "size"));
            vo.setPageNum(getIntegerSafely(itemMap, "pageNum"));
            vo.setStep(getIntegerSafely(itemMap, "step"));
            vo.setId(getStringSafely(itemMap, "id"));
            vo.setName(getStringSafely(itemMap, "name"));
            vo.setDbType(getStringSafely(itemMap, "dbType"));
            vo.setIp(getStringSafely(itemMap, "ip"));
            vo.setPort(getStringSafely(itemMap, "port"));
            vo.setUsername(getStringSafely(itemMap, "username"));
            vo.setPassword(getStringSafely(itemMap, "password"));
            vo.setDbName(getStringSafely(itemMap, "dbName"));
            vo.setRemark(getStringSafely(itemMap, "remark"));
            vo.setPositionType(getIntegerSafely(itemMap, "positionType"));
            vo.setPositionTypeName(getStringSafely(itemMap, "positionTypeName"));
            vo.setCdcMode(getStringSafely(itemMap, "cdcMode"));
            vo.setParam(getStringSafely(itemMap, "param"));
            vo.setOwner(getStringSafely(itemMap, "owner"));
            vo.setCreateDate(getStringSafely(itemMap, "createDate"));

            // 处理deptId字段，可能是Long类型
            Object deptIdObj = itemMap.get("deptId");
            if (deptIdObj instanceof Number) {
                vo.setDeptId(((Number) deptIdObj).longValue());
            } else if (deptIdObj instanceof String) {
                try {
                    vo.setDeptId(Long.parseLong((String) deptIdObj));
                } catch (NumberFormatException e) {
                    log.warn("[convertToDataSourceVOList][deptId转换Long失败](value: {})", deptIdObj);
                }
            }

            vo.setDeptName(getStringSafely(itemMap, "deptName"));

            resultList.add(vo);
        }

        return resultList;
    }

    /**
     * 将数据列表转换为DataNum7DayItemVO列表
     */
    private List<DataNum7DayItemVO> convertToDataNum7DayItemVOList(List<Map<String, Object>> dataList) {
        List<DataNum7DayItemVO> resultList = new ArrayList<>();

        for (Map<String, Object> itemMap : dataList) {
            DataNum7DayItemVO vo = new DataNum7DayItemVO();

            // 处理dataNum字段，使用BigDecimal避免精度丢失
            Object dataNumObj = itemMap.get("dataNum");
            if (dataNumObj != null) {
                if (dataNumObj instanceof Number) {
                    vo.setDataNum(new BigDecimal(dataNumObj.toString()));
                } else if (dataNumObj instanceof String) {
                    vo.setDataNum(new BigDecimal((String) dataNumObj));
                }
            }

            vo.setDay(getStringSafely(itemMap, "day"));

            resultList.add(vo);
        }

        return resultList;
    }

    /**
     * 将数据Map转换为TaskDistributionRespVO
     */
    private TaskDistributionRespVO convertToTaskDistributionRespVO(Map<String, Object> dataMap) {
        TaskDistributionRespVO vo = new TaskDistributionRespVO();

        vo.setApiTaskNum(getIntegerSafely(dataMap, "apiTaskNum"));
        vo.setEntireDbNum(getIntegerSafely(dataMap, "entireDbNum"));
        vo.setDagNum(getIntegerSafely(dataMap, "dagNum"));
        vo.setDagDataNum(getLongSafely(dataMap, "dagDataNum"));
        vo.setTaskDataNum(getLongSafely(dataMap, "taskDataNum"));
        vo.setCdcNum(getIntegerSafely(dataMap, "cdcNum"));
        vo.setTaskNum(getIntegerSafely(dataMap, "taskNum"));

        return vo;
    }

    /**
     * 安全获取Long类型值
     */
    private Long getLongSafely(Map<String, Object> dataMap, String key) {
        Object value = dataMap.get(key);
        if (value instanceof Number) {
            return ((Number) value).longValue();
        } else if (value instanceof String) {
            try {
                return Long.parseLong((String) value);
            } catch (NumberFormatException e) {
                log.warn("[getLongSafely][字段转换Long失败](key: {}, value: {})", key, value, e);
                return null;
            }
        }
        return null;
    }

    /**
     * 将数据Map转换为TableRankingRespVO
     */
    @SuppressWarnings("unchecked")
    private TableRankingRespVO convertToTableRankingRespVO(Map<String, Object> dataMap) {
        TableRankingRespVO vo = new TableRankingRespVO();

        // 转换数据空间排名
        List<Map<String, Object>> dataSpaceList = (List<Map<String, Object>>) dataMap.get("dataSpace");
        if (dataSpaceList != null) {
            List<TableRankingItemVO> dataSpaceVOList = new ArrayList<>();
            for (int i = 0; i < dataSpaceList.size(); i++) {
                Map<String, Object> itemMap = dataSpaceList.get(i);
                TableRankingItemVO itemVO = convertToTableRankingItemVO(itemMap);
                // 设置排名（从1开始）
                itemVO.setRank(i + 1);
                dataSpaceVOList.add(itemVO);
            }
            vo.setDataSpace(dataSpaceVOList);
        }

        // 转换数据数量排名
        List<Map<String, Object>> dataNumList = (List<Map<String, Object>>) dataMap.get("dataNum");
        if (dataNumList != null) {
            List<TableRankingItemVO> dataNumVOList = new ArrayList<>();
            for (int i = 0; i < dataNumList.size(); i++) {
                Map<String, Object> itemMap = dataNumList.get(i);
                TableRankingItemVO itemVO = convertToTableRankingItemVO(itemMap);
                // 设置排名（从1开始）
                itemVO.setRank(i + 1);
                dataNumVOList.add(itemVO);
            }
            vo.setDataNum(dataNumVOList);
        }

        return vo;
    }

    /**
     * 将单个排名项Map转换为TableRankingItemVO
     */
    private TableRankingItemVO convertToTableRankingItemVO(Map<String, Object> itemMap) {
        TableRankingItemVO vo = new TableRankingItemVO();

        vo.setId(getStringSafely(itemMap, "id"));
        vo.setName(getStringSafely(itemMap, "name"));
        vo.setCatalog(getStringSafely(itemMap, "catalog"));
        vo.setValue(getStringSafely(itemMap, "value"));
        // rank字段在外部设置，因为需要根据列表位置计算

        return vo;
    }

    /**
     * 将响应Map转换为CatalogIndexDetailsRespVO
     */
    @SuppressWarnings("unchecked")
    private CatalogIndexDetailsRespVO convertToCatalogIndexDetailsRespVO(Map<String, Object> responseMap) {
        CatalogIndexDetailsRespVO resultVO = new CatalogIndexDetailsRespVO();

        // 转换数据列表
        List<Map<String, Object>> dataList = (List<Map<String, Object>>) responseMap.get("data");
        if (dataList != null) {
            List<CatalogIndexDetailsItemVO> itemVOList = new ArrayList<>();
            for (Map<String, Object> itemMap : dataList) {
                CatalogIndexDetailsItemVO itemVO = new CatalogIndexDetailsItemVO();

                // 处理catalogArr数组
                List<String> catalogArrList = (List<String>) itemMap.get("catalogArr");
                if (catalogArrList != null) {
                    itemVO.setCatalogArr(catalogArrList.toArray(new String[0]));
                }

                itemVO.setCatalogId(getStringSafely(itemMap, "catalogId"));
                itemVO.setCatalogPath(getStringSafely(itemMap, "catalogPath"));
                itemVO.setLevel(getIntegerSafely(itemMap, "level"));
                itemVO.setAssetNum(getStringSafely(itemMap, "assetNum"));
                itemVO.setDataNum(getStringSafely(itemMap, "dataNum"));
                itemVO.setDataSpace(getStringSafely(itemMap, "dataSpace"));

                itemVOList.add(itemVO);
            }
            resultVO.setData(itemVOList);
        }

        // 转换分页信息
        Map<String, Object> pageInfoMap = (Map<String, Object>) responseMap.get("pageInfo");
        if (pageInfoMap != null) {
            PageInfoVO pageInfoVO = new PageInfoVO();
            pageInfoVO.setOffset(getIntegerSafely(pageInfoMap, "offset"));
            pageInfoVO.setSize(getIntegerSafely(pageInfoMap, "size"));
            pageInfoVO.setPageNum(getIntegerSafely(pageInfoMap, "pageNum"));
            pageInfoVO.setStep(getIntegerSafely(pageInfoMap, "step"));
            pageInfoVO.setPages(getIntegerSafely(pageInfoMap, "pages"));
            pageInfoVO.setTotal(getIntegerSafely(pageInfoMap, "total"));
            resultVO.setPageInfo(pageInfoVO);
        }

        return resultVO;
    }

    /**
     * 将数据Map转换为HomeTopIndexRespVO
     */
    @SuppressWarnings("unchecked")
    private HomeTopIndexRespVO convertToHomeTopIndexRespVO(Map<String, Object> dataMap) {
        HomeTopIndexRespVO vo = new HomeTopIndexRespVO();

        // 转换apiIndex
        Map<String, Object> apiIndexMap = (Map<String, Object>) dataMap.get("apiIndex");
        if (apiIndexMap != null) {
            vo.setApiIndex(convertToIndexItemVO(apiIndexMap));
        }

        // 转换indicatorIndex
        Map<String, Object> indicatorIndexMap = (Map<String, Object>) dataMap.get("indicatorIndex");
        if (indicatorIndexMap != null) {
            vo.setIndicatorIndex(convertToIndexItemVO(indicatorIndexMap));
        }

        // 转换sourceIndex
        Map<String, Object> sourceIndexMap = (Map<String, Object>) dataMap.get("sourceIndex");
        if (sourceIndexMap != null) {
            vo.setSourceIndex(convertToIndexItemVO(sourceIndexMap));
        }

        // 转换standardIndex
        Map<String, Object> standardIndexMap = (Map<String, Object>) dataMap.get("standardIndex");
        if (standardIndexMap != null) {
            vo.setStandardIndex(convertToIndexItemVO(standardIndexMap));
        }

        // 转换tableIndex
        Map<String, Object> tableIndexMap = (Map<String, Object>) dataMap.get("tableIndex");
        if (tableIndexMap != null) {
            vo.setTableIndex(convertToIndexItemVO(tableIndexMap));
        }

        return vo;
    }

    /**
     * 将单个指标Map转换为IndexItemVO
     */
    private IndexItemVO convertToIndexItemVO(Map<String, Object> indexMap) {
        IndexItemVO vo = new IndexItemVO();

        vo.setCatalogId(getStringSafely(indexMap, "catalogId"));
        vo.setCatalogName(getStringSafely(indexMap, "catalogName"));
        vo.setAssetNum(getStringSafely(indexMap, "assetNum"));
        vo.setAssetNumChain(getStringSafely(indexMap, "assetNumChain"));
        vo.setAssetNumYear(getStringSafely(indexMap, "assetNumYear"));
        vo.setDataNum(getStringSafely(indexMap, "dataNum"));
        vo.setDataNumChain(getStringSafely(indexMap, "dataNumChain"));
        vo.setDataNumYear(getStringSafely(indexMap, "dataNumYear"));
        vo.setDataSpace(getStringSafely(indexMap, "dataSpace"));
        vo.setDataSpaceChain(getStringSafely(indexMap, "dataSpaceChain"));
        vo.setDataSpaceYear(getStringSafely(indexMap, "dataSpaceYear"));

        return vo;
    }

    /**
     * 将数据列表转换为SectionOptionVO列表
     */
    private List<SectionOptionVO> convertToSectionOptionVOList(List<Map<String, Object>> dataList) {
        List<SectionOptionVO> resultList = new ArrayList<>();

        for (Map<String, Object> itemMap : dataList) {
            SectionOptionVO vo = new SectionOptionVO();

            vo.setId(getStringSafely(itemMap, "id"));
            vo.setName(getStringSafely(itemMap, "name"));
            vo.setHierarchy(getStringSafely(itemMap, "hierarchy"));
            vo.setTenantId(getStringSafely(itemMap, "tenantId"));
            vo.setStatus(getStringSafely(itemMap, "status"));
            vo.setRank(getIntegerSafely(itemMap, "rank"));
            vo.setUpdateTime(getStringSafely(itemMap, "updateTime"));
            vo.setUpdateUser(getStringSafely(itemMap, "updateUser"));

            resultList.add(vo);
        }

        return resultList;
    }

    /**
     * 将响应Map转换为AccessStatisticsRespVO
     */
    private AccessStatisticsRespVO convertToAccessStatisticsRespVO(Map<String, Object> responseMap) {
        AccessStatisticsRespVO vo = new AccessStatisticsRespVO();

        vo.setSuccess((Boolean) responseMap.get("success"));
        vo.setCode((Integer) responseMap.get("code"));
        vo.setMessage(getStringSafely(responseMap, "message"));
        vo.setData(responseMap.get("data")); // 保持原始数据结构
        vo.setPageInfo(responseMap.get("pageInfo"));
        vo.setExt(responseMap.get("ext"));

        return vo;
    }

    /**
     * 安全获取String类型值
     */
    private String getStringSafely(Map<String, Object> dataMap, String key) {
        Object value = dataMap.get(key);
        return value != null ? value.toString() : null;
    }

    /**
     * 安全获取Integer类型值
     */
    private Integer getIntegerSafely(Map<String, Object> dataMap, String key) {
        Object value = dataMap.get(key);
        if (value instanceof Number) {
            return ((Number) value).intValue();
        } else if (value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                log.warn("[getIntegerSafely][字段转换Integer失败](key: {}, value: {})", key, value, e);
                return null;
            }
        }
        return null;
    }

    /**
     * 将数据列表转换为CatalogIndexItemVO列表
     */
    private List<CatalogIndexItemVO> convertToCatalogIndexItemVOList(List<Map<String, Object>> dataList) {
        List<CatalogIndexItemVO> resultList = new ArrayList<>();

        for (Map<String, Object> itemMap : dataList) {
            CatalogIndexItemVO vo = new CatalogIndexItemVO();

            vo.setCatalogId(getStringSafely(itemMap, "catalogId"));
            vo.setCatalogName(getStringSafely(itemMap, "catalogName"));
            vo.setAssetNum(getStringSafely(itemMap, "assetNum"));
            vo.setAssetNumChain(getStringSafely(itemMap, "assetNumChain"));
            vo.setAssetNumYear(getStringSafely(itemMap, "assetNumYear"));
            vo.setDataNum(getStringSafely(itemMap, "dataNum"));
            vo.setDataNumChain(getStringSafely(itemMap, "dataNumChain"));
            vo.setDataNumYear(getStringSafely(itemMap, "dataNumYear"));
            vo.setDataSpace(getStringSafely(itemMap, "dataSpace"));
            vo.setDataSpaceChain(getStringSafely(itemMap, "dataSpaceChain"));
            vo.setDataSpaceYear(getStringSafely(itemMap, "dataSpaceYear"));
            vo.setChildrenList(itemMap.get("childrenList"));

            resultList.add(vo);
        }

        return resultList;
    }
}